package com.chaber.containers.beans.searchcriteria;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;

import com.chaber.containers.beans.ProductCategoryData;
import com.chaber.containers.beans.ProductData;

public class ProductSearchCriteria implements Specification<ProductData> {

	private String barCode;
	
	private String name;
	
	private Integer amount;

	private Date cdFrom;
	
	private Date cdTo;
	
	private Date mdFrom;
	
	private Date mdTo;
	
	private Integer categoryId;
	
	@Override
	public Predicate toPredicate(Root<ProductData> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
		
		List<Predicate> predicates = new ArrayList<>();
		
		if (!StringUtils.isEmpty(this.barCode)) {
			Predicate barCodePredicate = cb.like(root.get("barCode").as(String.class), this.barCode);
			predicates.add(barCodePredicate);
		}
		
		if (!StringUtils.isEmpty(this.name)) {
			Predicate namePredicate = cb.like(root.get("name").as(String.class), this.name);
			predicates.add(namePredicate);
		}
		
		if (this.amount != null) {
			Predicate amountPredicate = cb.equal(root.get("amount").as(Integer.class), this.amount);
			predicates.add(amountPredicate);
		}
		
		if (this.cdFrom != null) {
			Predicate cdPredicate = cb.greaterThanOrEqualTo(root.get("creationDate").as(Date.class), this.cdFrom);
			predicates.add(cdPredicate);
		}
		
		if (this.cdTo != null) {
			Predicate cdPredicate = cb.lessThanOrEqualTo(root.get("creationDate").as(Date.class), this.cdTo);
			predicates.add(cdPredicate);
		}
		
		if (this.mdFrom != null) {
			Predicate mdPredicate = cb.greaterThanOrEqualTo(root.get("modificationDate").as(Date.class), this.mdFrom);
			predicates.add(mdPredicate);
		}
		
		if (this.mdTo != null) {
			Predicate mdPredicate = cb.lessThanOrEqualTo(root.get("modificationDate").as(Date.class), this.mdTo);
			predicates.add(mdPredicate);
		}
		
		if (this.categoryId != null) {
			Join<ProductData, ProductCategoryData> join = root.join("assignedCategory"); 
			Predicate categoryIdPredicate = cb.equal(join.get("id"), this.categoryId);
			predicates.add(categoryIdPredicate);
		}

		return cb.and(predicates.toArray(new Predicate[0]));
	}

	public String getBarCode() {
		return barCode;
	}

	public void setBarCode(String barCode) {
		this.barCode = barCode;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAmount() {
		return amount;
	}

	public void setAmount(Integer amount) {
		this.amount = amount;
	}

	public Date getCdFrom() {
		return cdFrom;
	}

	public void setCdFrom(Date cdFrom) {
		this.cdFrom = cdFrom;
	}

	public Date getCdTo() {
		return cdTo;
	}

	public void setCdTo(Date cdTo) {
		this.cdTo = cdTo;
	}

	public Date getMdFrom() {
		return mdFrom;
	}

	public void setMdFrom(Date mdFrom) {
		this.mdFrom = mdFrom;
	}

	public Date getMdTo() {
		return mdTo;
	}

	public void setMdTo(Date mdTo) {
		this.mdTo = mdTo;
	}

	public Integer getCategoryId() {
		return categoryId;
	}

	public void setCategoryId(Integer categoryId) {
		this.categoryId = categoryId;
	}
}
